"""
poll 适用平台unix、linux。windows程序无法运行
poll 多路复用
"""
from socket import *
from select import *

# 创建关注的IO
s = socket()
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 8888))
s.listen(5)

# 创建poll
p = poll()
# 建立查找字典{fileno:io_obj}
fdmap = {s.fileno(): s}

# 设置监控io事件发生
p.register(s, POLLIN | POLLERR)

while True:
    # 阻塞等待IO发生
    # 客户端端口会同时返回两个元组，类型分别是POLLIN和POLLHUP
    events = p.poll()
    # 遍历列表处理IO
    for fd, event in events:
        if fd == s.fileno():
            c, addr = fdmap[fd].accept()
            print('Connect from:', addr)
            # 添加新的关注事件
            p.register(c, POLLIN | POLLHUP)
            fdmap[c.fileno()] = c
        # elif event & POLLHUP:
        #     print('客户端退出')
        #     # 取消关注（可传递描述符或对象）
        #     p.unregister(fd)
        #     fdmap[fd].close()
        #     # 从字典中删除
        #     del fdmap[fd]
        # 客户端发送消息
        elif event & POLLIN:
            data = fdmap[fd].recv(1024)
            # 客户端端口会同时返回两个元组，类型分别是POLLIN和POLLHUP,所以需要判断
            # 断开发生时data得到空此时POLLIN也会就绪
            if not data:
                print('客户端退出')
                # 取消关注（可传递描述符或对象）
                p.unregister(fd)
                fdmap[fd].close()
                # 从字典中删除
                del fdmap[fd]
                continue
            print(data.decode())
            fdmap[fd].send(b'OK')
